package de.blinkt.openvpn.advancedconnection;

import java.util.ArrayList;
import java.util.HashSet;
import java.util.Set;

import android.app.Activity;
import android.net.NetworkInfo;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ListView;
import de.blinkt.openvpn.NetworkUtil;
import de.blinkt.openvpn.R;
import de.blinkt.openvpn.VpnProfile;
import de.blinkt.openvpn.VpnProfile.VpnNetworkInfo;

class NetworkListPreferencePresenter {

	public static final String RESTRICT_RECONNECT_TO_NETWORKS_LIST_PREF_KEY = "restrictReconnectToNetworksList";
	private NetworkListPreferenceView mView;
	private Activity mActivity;
	private ArrayAdapter<NetworkListItem> mAdapter;
	

	public NetworkListPreferencePresenter(NetworkListPreferenceView view, Activity activity) {
		mView = view;
		mActivity = activity;
	}

	void loadSettings(VpnProfile profile) {
		//move from profile -> preference
		Set<String> pref = new HashSet<String>();
		for (VpnNetworkInfo value : profile.mRestrictedNetworksList) {
			pref.add(value.mNetworkType + ":" + value.mNetworkSubtype + ":" + value.mNetworkTypeName + ":" + value.mNetworkSubtypeName + ":" + value.mNetworkName);
		}
		
		mView.getSharedPreferences().edit().putStringSet(RESTRICT_RECONNECT_TO_NETWORKS_LIST_PREF_KEY, pref).commit();
		
	}

	private Set<NetworkListItem> buildValues(Iterable<VpnProfile.VpnNetworkInfo> iter) {
		Set<NetworkListItem> s = new HashSet<NetworkListItem>();
		for (VpnProfile.VpnNetworkInfo info : iter) {
			s.add(new NetworkListItem(info.mNetworkType, info.mNetworkTypeName, info.mNetworkSubtype, info.mNetworkSubtypeName, info.mNetworkName));
		}
		return s;
	}

	public void saveSettings(VpnProfile profile) {
		//move from preference -> profile
		ArrayList<VpnProfile.VpnNetworkInfo> profileValues = parsePref();
		profile.mRestrictedNetworksList = (VpnNetworkInfo[]) profileValues.toArray(new VpnNetworkInfo[profileValues.size()]);
	}

	private ArrayList<VpnProfile.VpnNetworkInfo> parsePref() {
		Set<String> prefs = mView.getSharedPreferences().getStringSet(RESTRICT_RECONNECT_TO_NETWORKS_LIST_PREF_KEY, new HashSet<String>());
		ArrayList<VpnProfile.VpnNetworkInfo> profileValues = new ArrayList<VpnProfile.VpnNetworkInfo>(prefs.size());
		for (String value : prefs) {
			String[] split = value.split("\\:", 5);
			if(split.length == 5){
				VpnProfile.VpnNetworkInfo profileValue = new VpnProfile.VpnNetworkInfo();
				profileValue.mNetworkType = Integer.parseInt(split[0]);
				profileValue.mNetworkSubtype = Integer.parseInt(split[1]);
				profileValue.mNetworkTypeName = split[2];
				profileValue.mNetworkSubtypeName = split[3];
				profileValue.mNetworkName = split[4];
				profileValues.add(profileValue);
			}
		}
		return profileValues;
	}

	protected void removeSelectedNetwork() {
		for(int i = 0; i < mAdapter.getCount(); i++){
			NetworkListItem item = mAdapter.getItem(i);
			if(item.isChecked()){
				mAdapter.remove(item);
				break;
			}
			
		}
		
		mView.getRemoveButton().setEnabled(mAdapter.getCount() > 0);
	}

	protected void addCurrentNetwork() {
		// TODO: Better model is to use network state receiver to listen for
		// network changes to ensure currently connectect
		// and enable/disable add button based on that value

		// attach to connectivity manager
		NetworkInfo activeNetworkInfo = NetworkUtil.getCurrentNetworkInfo(mActivity);
		

		try {
			if (activeNetworkInfo != null && activeNetworkInfo.isConnectedOrConnecting()) {
				NetworkListItem newItem = new NetworkListItem(activeNetworkInfo.getType(), activeNetworkInfo.getTypeName(), activeNetworkInfo.getSubtype(),  activeNetworkInfo.getSubtypeName(), "UNKNOWN");
				newItem.setName(NetworkUtil.extractNetworkName(mActivity, activeNetworkInfo));
				mAdapter.add(newItem);
			}
		} catch (IllegalArgumentException e) {
			mView.showUnableToAddNetworkError();
		}

	}

	public void initView() {
		//move from preference -> model
//		mAdapter = new ArrayAdapter<NetworkListItem>(mActivity, R.layout.network_selector,new ArrayList<NetworkListItem>(buildValues(parsePref())));
//		mView.getNetworkList().setAdapter(mAdapter);
//		mView.getNetworkList().setChoiceMode(ListView.CHOICE_MODE_SINGLE);
//		mView.getRemoveButton().setEnabled(false);

		registerChangeHandlers();
	}
	
	public void listSaved() {
		Set<String> pref = new HashSet<String>();
		for(int i = 0; i < mAdapter.getCount(); i++){
			pref.add(mAdapter.getItem(i).getType() + ":" + mAdapter.getItem(i).getSubtype() + ":" + mAdapter.getItem(i).getName());
			
		}
		
		mView.getSharedPreferences().edit().putStringSet(RESTRICT_RECONNECT_TO_NETWORKS_LIST_PREF_KEY, pref).commit();
	}


	private void registerChangeHandlers() {
		mView.getAddButton().setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				addCurrentNetwork();
			}
		});

		mView.getRemoveButton().setOnClickListener(new OnClickListener() {
			@Override
			public void onClick(View v) {
				removeSelectedNetwork();
			}
		});

		mView.getNetworkList().setOnItemClickListener(new OnItemClickListener() {

			@Override
			public void onItemClick(AdapterView<?> parent, View view, int position, long id) {
				mView.getRemoveButton().setEnabled(true);
				mAdapter.getItem(position).setChecked(true);
			}
		});
	}

	
	private static class NetworkListItem {
		private int mType;
		private int mSubtype;
		private String mName;
		private boolean mChecked;
		private String mTypeName;
		private String mSubtypeName;

		public NetworkListItem(int type, String typeName, int subtype, String subtypeName, String name){
			mType = type;
			mSubtype = subtype;
			mName = name;
			mTypeName = typeName;
			mSubtypeName = subtypeName;
			mChecked = false;
			
		}


		public boolean isChecked() {
			return mChecked;
		}

		public void setChecked(boolean checked) {
			mChecked = checked;
		}

		public int getType() {
			return mType;
		}

		public int getSubtype() {
			return mSubtype;
		}

		public String getName() {
			return mName;
		}
		
		public void setName(String name) {
			mName = name;
		}

		public String toString() {
			return mTypeName +  (mSubtypeName != null && mSubtypeName.length() > 0 ? ( " ( " + mSubtypeName + " ) ") : "") + " - " + mName; 
		}
	}



}
